package heap

import "jvm/nzpJvm/classfile"

// 字段的符号引用
type FieldRef struct {
	MemberRef
	field *Field
}

// 新建一个字段符号引用
func newFieldRef(pool *ConstantPool, info *classfile.ConstantFieldrefInfo) Constant {
	ref := &FieldRef{}
	ref.cp = pool
	ref.copyMemberRefInfo(&info.ConstantMemberRefInfo)
	return ref
}

// 获取字段的直接引用
func (self *FieldRef) ResolveField() *Field {
	if self.field == nil {
		self.resolveFieldRef()
	}
	return self.field
}

// 将字段的符号引用解析成直接引用
func (self *FieldRef) resolveFieldRef() {
	// 常量池所属的类，也就是触发符号解析的类
	d := self.cp.class
	// 字段的符号引用所属的类，也就是定义这个字段的类
	class := self.ResolveClass()
	// 在定义了这个字段的类中查找这个字段
	field := lookupField(class, self.name, self.descriptor)
	if field == nil {
		panic("java.lang.NoSuchFieldError")
	}
	// 当前类是否有权限访问此字段
	if !field.isAccessibleTo(d) {
		panic("java.lang.IllegalAccessError")
	}

	self.field = field
}

// 在指定的类中查找字段
func lookupField(class *Class, name string, descriptor string) *Field {
	// 在当前类中查找字段
	for _, field := range class.fields {
		if field.name == name && field.descriptor == descriptor {
			return field
		}
	}

	// 当前类中找不到，从接口中查找
	for _, aInterface := range class.interfaces {
		if field := lookupField(aInterface, name, descriptor); field != nil {
			return field
		}
	}
	// 接口中也找不到，从父类中查找
	if class.superClass != nil {
		return lookupField(class.superClass, name, descriptor)
	}
	return nil
}
